
package com.bnq.control.desktop;

import static com.oray.sunlogin.plugin.remotedesktop.CompressionModeConfig.MODE_HD;
import static com.oray.sunlogin.plugin.remotedesktop.CompressionModeConfig.MODE_SMOOTH;
import static com.oray.sunlogin.plugin.remotedesktop.CompressionModeConfig.MODE_SPEED;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.bnq.control.R;
import com.oray.commonutils.utils.BuildConfig;
import com.oray.sunlogin.bean.PluginParam;
import com.oray.sunlogin.manager.DesktopPluginManager;
import com.oray.sunlogin.manager.SoundPluginManager;
import com.oray.sunlogin.manager.bean.desktop.DesktopMove;
import com.oray.sunlogin.manager.encode.gles.GlUtil;
import com.oray.sunlogin.manager.encode.listener.YUVRenderListener;
import com.oray.sunlogin.manager.interfaces.KeyBoardViewChangeListener;
import com.oray.sunlogin.manager.opengl.GlSurfaceMaskLayer;
import com.oray.sunlogin.manager.opengl.MediaCodecUtils;
import com.oray.sunlogin.manager.util.ClipboardUtils;
import com.oray.sunlogin.manager.widget.RemoteDesktopSurfaceView;
import com.oray.sunlogin.plugin.JavaPlugin;
import com.oray.sunlogin.plugin.remotedesktop.CompressionBuild;
import com.oray.sunlogin.plugin.remotedesktop.DSPSetting;
import com.oray.sunlogin.plugin.remotedesktop.IRemoteDesktopListener;
import com.oray.sunlogin.plugin.remotesoundchat.IRemoteSoundChatListener;
import com.bnq.control.common.constant.CNTS;
import com.bnq.control.common.dialog.LoadingDialog;
import com.bnq.control.common.utils.DisplayUtils;
import com.bnq.control.common.utils.KeyBoardUtils;
import com.bnq.control.common.utils.PermissionUtils;
import com.bnq.control.common.utils.RemoteDesktopUtils;
import com.bnq.control.common.utils.ToastUtils;
import com.bnq.control.desktop.impl.BluetoothImpl;
import com.bnq.control.desktop.impl.NotificationImpl;
import com.bnq.control.desktop.impl.ScreenShotImpl;
import com.bnq.control.desktop.popup.DesktopModePopup;
import com.bnq.control.desktop.popup.MotionPopup;
import com.bnq.control.desktop.popup.MouseMenuPopup;
import com.bnq.control.desktop.popup.OperationXmlPopup;
import com.bnq.control.desktop.utils.SurfaceRecordUtils;
import com.bnq.control.desktop.view.CircleScroll;
import com.bnq.control.desktop.view.Mouse;
import com.bnq.control.desktop.xmlview.KeyboardBaseView;
import com.bnq.control.desktop.xmlview.KeyboardCtrlView;
import com.bnq.control.desktop.xmlview.KeyboardFunView;
import com.bnq.control.desktop.xmlview.OnPrepareViewDelegate;
import com.bnq.control.desktop.xmlview.OnSubViewClickListener;
import com.bnq.control.desktop.xmlview.OnSubViewTouchListener;

import java.io.File;

/**
 * 远程桌面UI, 展示远程桌面. 包括两种模式：查看模式和控制模式.
 *
 * @author lity
 */
public class RemoteDesktopActivity extends AppCompatActivity implements IRemoteDesktopListener, JavaPlugin.IConnectorListener
        , LoadingDialog.OnTimeoutListener, ViewTreeObserver.OnGlobalLayoutListener
        , RemoteDesktopUtils.OnTimerOutListener, KeyBoardViewChangeListener {
    private static final String TAG = RemoteDesktopActivity.class.getSimpleName();

    public static final String SOUND_ADDRESS = "sound_address";

    public static final String SOUND_SESSION = "sound_session";

    public static final int MODE_OBSERVE = 0;                           // 观看模式

    public static final int MODE_CONTROL = 1;                           // 控制模式

    private static final int FUNCTION_LOCK_SCREEN = 1;                  // 锁定屏幕

    private static final int FUNCTION_CLOSE_MOUSE = 2;                   // 关闭鼠标

    private static final int FUNCTION_SHOW_DESKTOP = 3;                 // 显示远程桌面

    private static final int FUNCTION_LOCK_DESKTOP = 4;                 // 锁定桌面

    private static final int FUNCTION_RESTART = 5;                      // 重启主机

    private static final int FUNCTION_CLOSE_REMOTE_DESKTOP = 6;         // 关闭主机

    private static final int FUNCTION_GUIDE = 7;                        // 手势指南

    private static final int FUNCTION_EXIT_CONTROL = 8;                 // 退出远控

    private static final int FUNCTION_OPEN_SOUND = 9;                   // 开启声音

    private static final int FUNCTION_SWITCH_SCREEN = 10;               // 切换屏幕

    private static final int FUNCTION_MORE_OPERATION = 11;              // 更多工具栏

    private static final int FUNCTION_MORE_CONTROL = 12;                // 更多控制栏

    private static final int FUNCTION_KEYBOARD = 13;                    // 键盘

    private static final int FUNCTION_WATCH_LOCK_SCREEN = 14;           // 观看模式下 锁定屏幕

    private boolean upKeyboard;                                         // 键盘更新
    private boolean bConnect = false;                                   // 声音插件连接状态
    private boolean isLoadingChangeModel;                               // 加载切换桌面模式
    protected boolean isCancelDesktop;                                  // 是否取消桌面连接
    private boolean isGetDataInfo;                                      // 是否已获取桌面信息
    private boolean isFirstInit;                                        // 是否第一次初始化
    private int changeMode;                                             // 改变的桌面模式
    private int currentMode;                                            // 当前的桌面模式
    private int keyboardHeight = 0;                                     // 键盘高度
    private int keyboardViewHeight = 0;                                 // 键盘view的高度
    private int screenHeight;                                           // 屏幕高度
    private int mMode = MODE_CONTROL;                                   // 远控模式
    private int mScreenOrientation;                                     // 屏幕方向
    private float y1, y2;                                               // 鼠标的y坐标
    private String address;                                             // 远控桌面连接地址
    private String session;                                             // 远控桌面session
    private final Rect temp = new Rect();                               // 点击区域
    private Activity mActivity;
    private SoundListener mSndListener;                                 // 声音插件状态监听
    private final EventListener mEventListener = new EventListener();   // 事件监听
    private DesktopPluginManager mDesktopManager;                       // 远控桌面管理
    private SoundPluginManager mSoundManager;                           // 声音管理
    private ViewGroup rootView;                                         // 根view
    private View mMenuToolBar;                                          // 底部功能栏
    private View mMenuPopBar;                                           // 底部菜单栏
    private Mouse mouse;
    private RemoteDesktopSurfaceView mSurfaceView;                      // GLSurfaceView
    private GlSurfaceMaskLayer mDesktopView;                            // 遮罩view
    private MouseMenuPopup mMouseMenuPop;                               // 鼠标功能pop
    private OperationXmlPopup mOpPopup;                                 // 底部更多功能pop
    private MotionPopup mMotionPopup;                                   // 手势操作pop
    private DesktopModePopup mDesktopModePopup;                         // 桌面模式切换pop
    private CircleScroll circleScroll;
    private KeyboardCtrlView mKeyboardCtrlView;
    private KeyboardFunView mKeyboardFunView;
    private KeyboardBaseView mKeyboardBaseView;
    private TextView mTv_desktop_menu_voice;
    private TextView mTv_desktop_menu_record;
    private TextView mTv_desktop_menu_lockscreen;
    private CheckBox mCb_desktop_menu_voice_checkbox;
    private CheckBox mCb_desktop_menu_record_checkbox;
    private LoadingDialog mLoadingDialog;
    private MediaCodecUtils codecUtils;                                 // MediaCodec工具类
    protected RemoteDesktopUtils remoteDesktopUtils;                    // 远控桌面工具类

    private final Handler mHandler = new Handler(Looper.getMainLooper());

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_remote_desktop);

        mDesktopManager = DesktopPluginManager.getInstance();
        mDesktopManager.addListener(this);
        mDesktopManager.addConnectorListener(this);
        mDesktopManager.resetNetworkDiagnosis();
        mDesktopManager.setContext(this);
        mDesktopManager.setNotificationListener(new NotificationImpl());
        mDesktopManager.setScreenShotListener(new ScreenShotImpl());
        mDesktopManager.setBluetoothListener(new BluetoothImpl());

        remoteDesktopUtils = new RemoteDesktopUtils(mDesktopManager);
        remoteDesktopUtils.setOnTimerOutListener(this);

        mSoundManager = new SoundPluginManager();

        initView();
    }

    private void initView() {
        address = getIntent().getStringExtra(SOUND_ADDRESS);
        session = getIntent().getStringExtra(SOUND_SESSION);

        enableControl(true);
        //全屏模式，去掉虚拟按键
        mActivity = this;
        rootView = findViewById(R.id.fl_desktop);
        //键盘弹出，收起的监听
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            DisplayUtils.setFullScreenStatus(RemoteDesktopActivity.this);
            Rect r = new Rect();
            rootView.getWindowVisibleDisplayFrame(r);
            int screenHeight = rootView.getRootView().getHeight();
            int heightDifference = screenHeight - (r.bottom - r.top);
            updateKeyBoardChange(heightDifference);
        });

        mSurfaceView = findViewById(R.id.surface);
        mDesktopView = rootView.findViewById(R.id.remote_desktop_view);
        TextView tips = findViewById(R.id.tips);
        mDesktopView.setTip(tips);
        mDesktopView.setAndroidMode(false);

        initStatus();

        initMouse();

        // 初始化SurfaceView回调
        setSurfaceViewCreateListener(mSurfaceView, mDesktopManager);
        /*
          根据不同的控制模块 初始化不同的模块
           观看和控制
         */
        if (mMode == MODE_CONTROL) {
            mMenuToolBar = findViewById(R.id.desktop_menu_control);
        } else if (mMode == MODE_OBSERVE) {
            mMenuToolBar = findViewById(R.id.desktop_menu_watch);
        }
        mMenuPopBar = findViewById(R.id.remote_desktop_pop_viewgroup);

        mMenuPopBar.setVisibility(View.VISIBLE);

        mLoadingDialog = new LoadingDialog(this);
        mLoadingDialog.setOnTimeoutListener(this);
        mLoadingDialog.setTimeOut(30 * 1000);
        mLoadingDialog.setTips("退出中...");

        initMenuPop();

        initMenuTool();
    }

    private void initStatus() {
        mDesktopView.setCursorResource(R.drawable.cursor_mornal);
        mDesktopView.setDesktopPluginManager(mDesktopManager);
        mDesktopView.setAndroidMode(false);
        mDesktopView.setControl(true);
        mDesktopManager.setControlMode();
        if (null != rootView) rootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    public void setSurfaceViewCreateListener(RemoteDesktopSurfaceView surfaceView, DesktopPluginManager manager) {
        mDesktopView.setGlSurfaceView(surfaceView);
        codecUtils = new MediaCodecUtils();
        surfaceView.getSunloginRender().setOnSurfaceCreateListener(surface ->
                codecUtils.setSurfaceView(surfaceView, surface, manager, this::updateDesktopRect));

        mDesktopView.drawFirstFrame(true);
        manager.setOnYUVRenderListener(new YUVRenderListener() {
            @Override
            public void onRenderYUV(int width, int height, byte[] y, byte[] u, byte[] v, boolean useNative) {
                // 渲染yuv数据 软解码
                surfaceView.getSunloginRender().setRenderType(GlUtil.RENDER_YUV);
                if (null != codecUtils) codecUtils.releaseMediaCodec();
                surfaceView.setYUVData(width, height, y, u, v, useNative);
            }

            @Override
            public void initMediaCodec(int width, int height, byte[] csd_0, byte[] csd_1, String mime) {
                // 初始化 mediacodec
                codecUtils.initMediaCodec(width, height, mime);
                surfaceView.getSunloginRender().setRenderType(GlUtil.RENDER_MEDIACODEC);
            }

            @Override
            public void outputFormatChange(int width, int height) {
                mDesktopView.updateAlignmentSize(width, height);
            }

            @Override
            public void decodeFrameSize(int width, int height) {
                updateDesktopRect(width, height);
            }

            @Override
            public void decodeFrame(int dataSize, byte[] data) {
                codecUtils.decodeFrameAsync(dataSize, data);
            }

            @Override
            public void useNativeRenderFilter(boolean useNative) {
                surfaceView.setUseNativeRender(useNative);
            }
        });
    }


    /**
     * 初始化鼠标
     */
    private void initMouse() {
        mouse = findViewById(R.id.remote_desktop_mouse);
        if (mMode == MODE_OBSERVE) {
            mouse.setVisibility(View.INVISIBLE);
        } else {
            mouse.setVisibility(View.VISIBLE);
        }
        circleScroll = rootView.findViewById(R.id.remote_desktop_circle);
        circleScroll.setVisibility(View.INVISIBLE);

        mouse.setMouseListener(new Mouse.MouseListener() {
            @Override
            public void OnScrollMove(MotionEvent event) {
                // 滚轮弹簧动画
                circleScroll.setCenterY(mouse.getTranslationY() + DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, mActivity));
                circleScroll.moveScoller(mouse.getTranslationX() + DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2,
                        mActivity), event.getRawY(), event);
                // 发送滚轮事件
                float[] pt = new float[]{mouse.getTranslationX(), mouse.getTranslationY()};
                mDesktopView.transformPointToDesktop(pt);
                mDesktopView.SendMouseHover("", (int) pt[0], (int) pt[1], true);
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        y1 = event.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        y2 = event.getRawY();
                        if (y2 - y1 > 30) {
                            mDesktopView.SendMouseWheel("", (int) pt[0], (int) pt[1], 100, true);
                            y1 = y2;
                        } else if (y2 - y1 < -30) {
                            mDesktopView.SendMouseWheel("", (int) pt[0], (int) pt[1], -100, true);
                            y1 = y2;
                        }
                        break;
                }
            }

            @Override
            public void OnRightUp() {
                onMouseRightClick(true);
            }

            @Override
            public void OnRightDown() {
                onMouseRightClick(false);
            }

            @Override
            public void OnBottomDown() {
            }

            @Override
            public void OnBottomUp() {
                if (mouse.isShown()) mouse.setVisibility(View.INVISIBLE);
                showMouseMenuPopupWindow();
            }

            @Override
            public void OnLeftUp() {
                onMouseLeftClick(true);
            }

            @Override
            public void OnLeftDown() {
                onMouseLeftClick(false);
            }

            @Override
            public void OnMouseMove(float dx, float dy) {
                float[] temp = new float[2];
                DesktopMove desktopMove = RemoteDesktopUtils.getDesktopMove((int) dx, (int) dy, keyboardHeight,
                        (int) mouse.getTranslationX(), (int) mouse.getTranslationY(), getBaseContext());
                float transY = mouse.getTranslationY() + dy;
                float transX = mouse.getTranslationX() + dx;
                boolean containsTransX = mDesktopView.containPointDesktopX(transX);
                boolean containsTransY = mDesktopView.containPointDesktopY(transY);
                if (containsTransX || (transX >= mDesktopView.mDesktopRect.right && dx < 0)
                        || (transX <= mDesktopView.mDesktopRect.left && dx > 0))
                    mouse.setTranslationX(transX);
                if ((containsTransY || (transY >= mDesktopView.mDesktopRect.bottom && dy < 0)
                        || (transY <= mDesktopView.mDesktopRect.top && dy > 0)))
                    mouse.setTranslationY(transY);
                mDesktopView.setStopMoveDesktop(desktopMove.isStopMoveDesktop());
                if (!desktopMove.isStopMoveDesktop())
                    mDesktopView.moveDesktopView(desktopMove.getDx(), desktopMove.getDy(), desktopMove.getLocationX(), desktopMove.getLocationY());
                temp[0] = transX;
                temp[1] = transY;
                if (mDesktopView.transformPointToDesktop(temp) && null != mDesktopManager)       // 发送移动事件
                    mDesktopView.SendMouseMove("LBUTTON", (int) temp[0], (int) temp[1], true);
            }

            @Override
            public void OnCenterDoubleCLick() {
                mouse.toSmallMouse();
                mDesktopView.setStopMoveDesktop(true);
            }

            @Override
            public void onCenterDown() {
            }

            @Override
            public void OnScrollUp() {
                circleScroll.setVisibility(View.INVISIBLE);
            }

            @Override
            public void OnSmallMouseClick() {
                if (mouse.isSmallMouseClickable()) {
                    mouse.toBigMouse();
                }
            }

            @Override
            public void OnSmallMouseMove(float dx, float dy) {
            }

            @Override
            public void toSide() {
                if (!upKeyboard) {
                    if (mDesktopView.mDesktopRect.height() >= DisplayUtils.getScreenHeight(mActivity)
                            && (mDesktopView.mDesktopRect.bottom < DisplayUtils.getScreenHeight(mActivity))) {
                        mDesktopView.moveRectToBottomEdge();
                    }
                    if (mDesktopView.mDesktopRect.right < DisplayUtils.getScreenWidth(mActivity) &&
                            mDesktopView.mDesktopRect.width() >= DisplayUtils.getScreenWidth(mActivity)) {
                        mDesktopView.moveRectToRightEdge();
                    }
                    mDesktopView.adjustView();
                }
            }

            @Override
            public void toCenter() {
            }

            @Override
            public void clickUnable() {
            }

            @Override
            public void OnDeleteClick() {
                mDesktopView.setStopMoveDesktop(true);
            }

        });
        mouse.setTranslationX((DisplayUtils.getScreenWidth(mActivity) >> 1)
                - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, mActivity));
        mouse.setTranslationY((DisplayUtils.getScreenHeight(mActivity) >> 1)
                - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, mActivity));
    }

    private void setMouseMoveHeight(int height) {
        this.keyboardHeight = height;
        if (null != mouse) mouse.setMouseMoveHeight(height);
    }

    /**
     * 鼠标右键点击
     *
     * @param isActionUp 按键抬起
     */
    protected void onMouseRightClick(boolean isActionUp) {
        float[] pt = new float[2];
        pt[0] = mouse.getTranslationX();
        pt[1] = mouse.getTranslationY();
        if (null != mDesktopManager && mDesktopView.transformPointToDesktop(pt)) {
            if (isActionUp) {
                mDesktopView.SendMouseRBUp("", (int) pt[0], (int) pt[1], true);
            } else {
                mDesktopView.SendMouseRBDown("", (int) pt[0], (int) pt[1], true);
            }
        }
    }

    /**
     * 鼠标左键点击
     *
     * @param isActionUp 按键抬起
     */
    protected void onMouseLeftClick(boolean isActionUp) {
        float[] pt = new float[2];
        pt[0] = mouse.getTranslationX();
        pt[1] = mouse.getTranslationY();
        if (null != mDesktopManager && mDesktopView.transformPointToDesktop(pt)) {
            if (isActionUp) {
                mDesktopView.SendMouseLBUp("", (int) pt[0], (int) pt[1], true);
            } else {
                mDesktopView.SendMouseLBDown("", (int) pt[0], (int) pt[1], true);
            }
        }
    }

    /**
     * 添加底部菜单, 并为子菜单设定事件监听器
     */
    private void initMenuPop() {
        // 弹出更多功能
        View v = mMenuPopBar.findViewById(R.id.remote_desktop_toolbar_header);
        v.setOnClickListener(mEventListener);

        // 显示键盘
        v = mMenuPopBar.findViewById(R.id.remote_desktop_toolbar_keyboard);
        v.setOnClickListener(mEventListener);

        onPrepareView(rootView);
    }

    /**
     * show前, 界面上做必要的调整
     *
     * @param rootView 跟view
     */
    protected void onPrepareView(View rootView) {

        // 如果是观察模式, 隐藏必要的"选项"
        if (MODE_OBSERVE == mMode) {
            View view = rootView.findViewById(R.id.remote_desktop_toolbar_keyboard);
            view.setVisibility(View.GONE);
        }

        /*
          TODO
          测试用例 用于隐藏工具栏方法
         */
        // hideMenuPop(rootView,FUNCTION_MORE_CONTROL);
        // hideMenuPop(rootView,FUNCTION_KEYBOARD);
    }

    /**
     * 隐藏工具类方法
     *
     * @param view       目标view
     * @param functionId 功能id
     */
    private void hideMenuPop(View view, int functionId) {
        switch (functionId) {
            case FUNCTION_MORE_CONTROL:
                hideSubView(view, R.id.remote_desktop_toolbar_header);
                break;
            case FUNCTION_KEYBOARD:
                hideSubView(view, R.id.remote_desktop_toolbar_keyboard);
                break;
        }
    }

    /**
     * 添加底部菜单, 并为子菜单设定事件监听器
     */
    private void initMenuTool() {
        mMenuToolBar.findViewById(R.id.desktop_menu_exit_viewgroup).setOnClickListener(mEventListener);
        mMenuToolBar.findViewById(R.id.desktop_menu_switchscreen_viewgroup).setOnClickListener(mEventListener);

        if (mMode == MODE_CONTROL)
            mMenuToolBar.findViewById(R.id.desktop_menu_more_viewgroup).setOnClickListener(mEventListener);

        if (mMode == MODE_OBSERVE) {
            mMenuToolBar.findViewById(R.id.rl_destop_option_screen_viewgroup).setOnClickListener(mEventListener);
            mTv_desktop_menu_lockscreen = mMenuToolBar.findViewById(R.id.tv_desktop_menu_lockscreen);
        }

        mTv_desktop_menu_voice = mMenuToolBar.findViewById(R.id.tv_desktop_menu_voice);
        mTv_desktop_menu_record = mMenuToolBar.findViewById(R.id.tv_desktop_menu_record);

        mMenuToolBar.findViewById(R.id.desktop_menu_voice_viewgroup).setOnClickListener(mEventListener);
        mMenuToolBar.findViewById(R.id.desktop_menu_record_viewgroup).setOnClickListener(mEventListener);
        onPrepareMenuTool(mMenuToolBar);
    }

    /**
     * 初始化菜单
     */
    private void onPrepareMenuTool(View menu) {
        mCb_desktop_menu_voice_checkbox = menu.findViewById(R.id.desktop_menu_voice_checkbox);
        mCb_desktop_menu_voice_checkbox.setEnabled(true);
        mCb_desktop_menu_voice_checkbox.setChecked(false);

        mCb_desktop_menu_record_checkbox = menu.findViewById(R.id.desktop_menu_record_checkbox);
        mCb_desktop_menu_record_checkbox.setChecked(false);

        mTv_desktop_menu_voice.setText("开启声音");
        mTv_desktop_menu_record.setText("开启录像");


        /*
           TODO
           测试用例
           根据逻辑需要隐藏相应模式下对应的功能
         */
//        if (mMode == MODE_OBSERVE){
//            hideMenuTool(menu,FUNCTION_EXIT_CONTROL);
//            hideMenuTool(menu,FUNCTION_OPEN_SOUND);
//            hideMenuTool(menu,FUNCTION_SWITCH_SCREEN);
//            hideMenuTool(menu,FUNCTION_WATCH_LOCK_SCREEN);
//        }else {
//            hideMenuTool(menu,FUNCTION_EXIT_CONTROL);
//            hideMenuTool(menu,FUNCTION_OPEN_SOUND);
//            hideMenuTool(menu,FUNCTION_SWITCH_SCREEN);
//            hideMenuTool(menu,FUNCTION_MORE_OPERATION);
//        }
    }

    /**
     * 切换屏幕
     */
    private void showSwitchScreen() {
        // 隐藏/显示切换屏幕
        View v = mMenuToolBar.findViewById(R.id.desktop_menu_switchscreen_viewgroup);
        int screenCount = mDesktopManager.getScreenCount();
        v.setVisibility(screenCount > 1 ? View.VISIBLE : View.GONE);
    }

    /**
     * 隐藏工具类方法
     *
     * @param view       目标view
     * @param functionId 功能id
     */
    private void hideMenuTool(View view, int functionId) {
        switch (functionId) {
            case FUNCTION_EXIT_CONTROL:
                hideSubView(view, R.id.desktop_menu_exit_viewgroup);
                break;
            case FUNCTION_OPEN_SOUND:
                hideSubView(view, R.id.desktop_menu_voice_viewgroup);
                break;
            case FUNCTION_SWITCH_SCREEN:
                hideSubView(view, R.id.desktop_menu_switchscreen_viewgroup);
                break;
            case FUNCTION_MORE_OPERATION:
                hideSubView(view, R.id.desktop_menu_more_viewgroup);
                break;
            case FUNCTION_WATCH_LOCK_SCREEN:
                hideSubView(view, R.id.rl_destop_option_screen_viewgroup);
                break;
        }
    }

    /**
     * 根据可视区域变化监听键盘改变鼠标做出相应处理
     *
     * @param heightDifference 高度偏差
     */
    private void updateKeyBoardChange(int heightDifference) {
        mDesktopView.setKeyboardHeight(heightDifference);
        if (heightDifference == 0) {
            if (upKeyboard) {
                mDesktopView.adjustView();
                upKeyboard = false;
                if (mouse.isSmall()) {
                    mouse.setTranslationX(DisplayUtils.getScreenWidth(mActivity)
                            - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2 + Mouse.SMALL_MOUSE_SIZE / 2, mActivity));
                    mouse.setTranslationY(DisplayUtils.dp2px(30, mActivity));
                } else {
                    mouse.setTranslationX((DisplayUtils.getScreenWidth(mActivity) >> 1)
                            - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, mActivity));
                    mouse.setTranslationY((DisplayUtils.getScreenHeight(mActivity) >> 1) -
                            DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, mActivity));
                }
            }
        } else {
            upKeyboard = true;
            if (mouse.isSmall()) {
                mouse.setTranslationX(DisplayUtils.getScreenWidth(mActivity)
                        - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2 + Mouse.SMALL_MOUSE_SIZE / 2, mActivity));
                mouse.setTranslationY(DisplayUtils.dp2px(30, mActivity));
            } else {
                mouse.setTranslationX((DisplayUtils.getScreenWidth(mActivity) >> 1) - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, mActivity));
                mouse.setTranslationY(DisplayUtils.dp2px(50, mActivity));
            }
        }
    }

    @Override
    public void onGlobalLayout() {
        if (null != rootView) {
            setFullScreen();
            Rect r = new Rect();
            rootView.getWindowVisibleDisplayFrame(r);
            if (screenHeight <= 0)
                screenHeight = DisplayUtils.getDisplayScreenHeight(this);
            if (screenHeight < r.bottom) screenHeight = r.bottom;
        }
    }

    private void setFullScreen() {
        DisplayUtils.setFullScreenStatus(this);
    }

    @Override
    public void onFirstFrame() {
        if (null != mDesktopView) mDesktopView.drawFirstFrame(true);
        if (null != mDesktopView) mDesktopView.requestLayout();
        if (!isCancelDesktop) latelyGetScreenInfo();
        showSwitchScreen();
    }

    /**
     * 延时获取桌面数据信息
     */
    private void latelyGetScreenInfo() {
        if (!isGetDataInfo) {
            isGetDataInfo = true;
            ClipboardUtils.startClipMonitorService(this, mDesktopManager.getCurrentIndex());
            uploadFps();
        }
    }

    /**
     * 更新fps
     */
    private void uploadFps() {
        CompressionBuild.buildMaxFPS(mDesktopManager, 30);
    }

    @Override
    public void onNewFrame(int nError) {
        if (isLoadingChangeModel) {
            isLoadingChangeModel = false;
            this.currentMode = changeMode;
            if (null != remoteDesktopUtils) remoteDesktopUtils.closeChangeModeDialog();
        }
        mDesktopView.requestLayout();
    }


    /**
     * 更新窗口宽高
     *
     * @param width  宽度
     * @param height 高度
     */
    private void updateDesktopRect(int width, int height) {
        if (null != mDesktopView && width > 0 && height > 0) {
            mDesktopView.updateDesktopRect(width, height);
        }
    }

    /**
     * 获取当前远控的桌面模式
     */
    private int getCurrentDesktopMode() {
        return currentMode <= 0 ? CompressionBuild.getCompressModeFilter(mDesktopManager) : currentMode;
    }

    @Override
    public void onEnumScreen(int numbers) {
    }

    @Override
    public void onKickUser(int nError) {
    }

    @Override
    public int onDisplayChanged(int width, int height, int bpp) {
        if (null != mDesktopView && !mDesktopView.isSetDesktopRect()) {
            updateDesktopRect(width, height);
        }
        return 0;
    }

    @Override
    public int onSwitchScreenEvent(int errorcode) {
        return 0;
    }

    @Override
    public void OnScreenResolutionListReceived() {
        // displayChange();
    }

    /**
     * 切换被控分辨率
     */
    private void displayChange() {
        DSPSetting bestDSPSetting = DisplayUtils.dspSetting(this, mDesktopManager);
        if (null != bestDSPSetting && bestDSPSetting.getHeight() > 0 && bestDSPSetting.getWidth() > 0)
            mDesktopManager.changeDisplaySetting(bestDSPSetting.getWidth(), bestDSPSetting.getHeight(), 0);
    }

    @Override
    public void onSwitchHostEvent(int res, int errorCode) {
    }

    @Override
    public void onTimerOut(int dialogType) {
        isLoadingChangeModel = false;
        ToastUtils.showSingleToast("模式切换失败", getBaseContext());
    }

    @Override
    public void onKeyBoardChange(int height) {
        this.keyboardHeight = height;
        changeMouseMoveHeight();
    }

    @Override
    public void onKeyBoardViewChange(int height) {
        this.keyboardViewHeight = height;
        changeMouseMoveHeight();
    }

    private void changeMouseMoveHeight() {
        setMouseMoveHeight(keyboardHeight + keyboardViewHeight);
    }

    private class EventListener implements View.OnClickListener, OnPrepareViewDelegate,
            OnSubViewClickListener, OnSubViewTouchListener {
        @Override
        public void onClick(View v) {
            int vId = v.getId();
            if (vId == R.id.remote_desktop_toolbar_header) {
                mMenuToolBar.setVisibility(View.VISIBLE);
                mMenuPopBar.setVisibility(View.INVISIBLE);
            } else if (vId == R.id.remote_desktop_toolbar_keyboard) {
                KeyBoardUtils.showSoftInput(mDesktopView);
                showKeyboardCtrlView();
                mMenuPopBar.setVisibility(View.GONE);
            } else if (vId == R.id.desktop_menu_exit_viewgroup) {
                onBackPressed();
            } else if (vId == R.id.desktop_menu_voice_viewgroup) {
                if (!bConnect) {
                    ConnectSoundPlugin();
                }
                switchVoice();
            } else if (vId == R.id.desktop_menu_record_viewgroup) {
                switchRecord();
            } else if (vId == R.id.desktop_menu_switchscreen_viewgroup) {
                switchScreen();
            } else if (vId == R.id.desktop_menu_more_viewgroup) {
                if (null == mOpPopup) {
                    mOpPopup = new OperationXmlPopup(mActivity);
                    mOpPopup.setOnPrepareViewDelegate(mEventListener);
                    mOpPopup.setOnSubViewClickListener(mEventListener);
                }
                mOpPopup.show(mDesktopView);
            } else if (vId == R.id.remote_desktop_view) {
            } else if (vId == R.id.rl_destop_option_screen_viewgroup) {
                boolean lock;
                int tmpInt = mActivity.getRequestedOrientation();
                View ib = mMenuToolBar
                        .findViewById(R.id.desktop_option_screen_lock);
                lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT == tmpInt || ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE == tmpInt;
                if (lock) {
                    mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
                    Toast.makeText(mActivity, "屏幕锁定已解除", Toast.LENGTH_SHORT).show();
                    ib.setBackgroundResource(R.drawable.selector_ib_desktop_option_screenlock);
                    mTv_desktop_menu_lockscreen.setText("关闭屏幕旋转");
                } else {
                    ib.setBackgroundResource(R.drawable.selector_ib_desktop_option_screenunlock);
                    tmpInt = mActivity.getResources().getConfiguration().orientation;
                    if (Configuration.ORIENTATION_LANDSCAPE == tmpInt) {
                        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    } else {
                        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    }
                    mTv_desktop_menu_lockscreen.setText("开启屏幕旋转");
                    Toast.makeText(mActivity, "屏幕已锁定", Toast.LENGTH_SHORT).show();
                }
            }
        }

        @Override
        public void onPrepareView(Object sender, View rootView) {
            // 如果是观察模式, 隐藏必要的"选项"
            if (sender == mOpPopup) {
                prepareOption(rootView);
            }
        }

        @Override
        public void onSubViewClick(Object sender, View v) {
            if (sender == mOpPopup) {
                handleOption(v);
            } else if (sender == mMotionPopup) {
                handleMotion(v);
            } else if (sender == mKeyboardCtrlView) {
                handleKeyboardCtrl(v);
            } else if (sender == mKeyboardBaseView) {
                handleKeyboardBase(v);
            } else if (sender == mDesktopModePopup) {
                handleDesktopMode(v);
            }
        }

        @Override
        public boolean onSubViewTouch(Object sender, View v, MotionEvent event) {
            return sender == mKeyboardFunView && handleKeyboardFunKey(v, event);
        }
    }

    /**
     * 开启关闭录像
     */
    public void switchRecord() {
        if (PermissionUtils.hasStoragePermission(this)) {
            boolean isChecked = mCb_desktop_menu_record_checkbox.isChecked();
            if (isChecked) {
                mDesktopView.stopRecorder();
                Toast.makeText(mActivity, "录像已停止", Toast.LENGTH_SHORT).show();
                mTv_desktop_menu_record.setText("录像开启");
                mCb_desktop_menu_record_checkbox.setChecked(false);
            } else {
                File file = new File(SurfaceRecordUtils.getFilePath(mActivity), SurfaceRecordUtils.getFileName());
                if (!file.exists() && null != file.getParentFile()) file.getParentFile().mkdirs();
                mDesktopView.startRecorder(file.getAbsolutePath());
                Toast.makeText(mActivity, "正在开启录像", Toast.LENGTH_SHORT).show();
                mTv_desktop_menu_record.setText("录像关闭");
                mCb_desktop_menu_record_checkbox.setChecked(true);
            }
        } else {
            PermissionUtils.requestStoragePermission(this);
            Toast.makeText(this, "沒有SD卡读写权限", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 显示 工具栏预处理
     *
     * @param v 目标view
     */
    private void prepareOption(View v) {
        boolean isControl = isControl();
        // 屏幕锁
        int tmpInt = mActivity.getRequestedOrientation();
        String src;
        if (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT == tmpInt || ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE == tmpInt) {
            src = "开启屏幕旋转";
        } else {
            src = "关闭屏幕旋转";
        }
        TextView tv = v.findViewById(R.id.remote_option_lockscreen_textview);
        tv.setText(src);

        // 依据观看/控制模式来处理
        if (isControl) {
            showSubView(v, R.id.show_remote_desktop);
            showSubView(v, R.id.remote_desktop_showdesk_line);
            showSubView(v, R.id.restart_remote_host);
            showSubView(v, R.id.close_remote_host);
            showSubView(v, R.id.remote_desktop_shutdown_line);

            /*
              测试用例 由用户自己控制 需要隐藏哪些功能
               TODO
             */
//            boolean isMac = true;
//            if(isMac){
//                hideOperationFunction(v,FUNCTION_CONVERSATION);
//            }

        }
    }

    /**
     * 菜单栏点击事件处理
     *
     * @param v 目标view
     */
    private void handleOption(View v) {
        int id = v.getId();
        if (id == R.id.remote_option_close_mouse) {
            TextView tv_close_mouse = (TextView) v.findViewById(R.id.remote_option_close_mouse_textview);
            Drawable drawable_mouse;
            if (mouse.isShown()) {
                mouse.setVisibility(View.INVISIBLE);
                tv_close_mouse.setText("开启虚拟鼠标");
                drawable_mouse = mActivity.getResources().getDrawable(R.drawable.desktop_option_screen_openmouse);

            } else {
                mouse.setVisibility(View.VISIBLE);
                tv_close_mouse.setText("关闭虚拟鼠标");
                drawable_mouse = mActivity.getResources().getDrawable(R.drawable.desktop_option_screen_closemouse);
            }
            drawable_mouse.setBounds(0, 0, drawable_mouse.getMinimumWidth(), drawable_mouse.getMinimumHeight()); // 设置边界
            tv_close_mouse.setCompoundDrawables(drawable_mouse, null, null, null);
        } else if (id == R.id.remote_option_lockscreen) {
            boolean lock;
            int tmpInt = mActivity.getRequestedOrientation();
            Drawable drawable;
            lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT == tmpInt || ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE == tmpInt;
            if (lock) {
                mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
                Toast.makeText(mActivity, "屏幕锁定已解除", Toast.LENGTH_SHORT).show();
                drawable = mActivity.getResources().getDrawable(R.drawable.desktop_option_screen_lock_nomal_img_small);
            } else {
                drawable = mActivity.getResources().getDrawable(R.drawable.desktop_option_screen_unlock_img_small);
                tmpInt = mActivity.getResources().getConfiguration().orientation;
                if (Configuration.ORIENTATION_LANDSCAPE == tmpInt) {
                    mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                } else {
                    mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                }
                Toast.makeText(mActivity, "屏幕已锁定", Toast.LENGTH_SHORT).show();
            }
            drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); // 设置边界
            TextView tv = v.findViewById(R.id.remote_option_lockscreen_textview);
            tv.setCompoundDrawables(drawable, null, null, null);
        } else if (id == R.id.show_remote_desktop) {
            mDesktopManager.sendHotKeyMessage("D", "LWIN");
        } else if (id == R.id.lock_remote_desktop) {// 锁定桌面
            mDesktopManager.sendWinL();
        } else if (id == R.id.restart_remote_host) {// 重启远程主机
            mDesktopManager.restartRemote();
            Toast.makeText(RemoteDesktopActivity.this, "重启指令已发送", Toast.LENGTH_SHORT).show();
        } else if (id == R.id.close_remote_host) {// 关掉远程主机
            mDesktopManager.shutdownRemote();
            Toast.makeText(RemoteDesktopActivity.this, "关机指令已发送", Toast.LENGTH_SHORT).show();
        } else if (id == R.id.operation_gesture_guide) {// 手势操作指南
            if (null == mMotionPopup) {
                mMotionPopup = new MotionPopup(mActivity);
                mMotionPopup.setOnSubViewClickListener(mEventListener);
            }
            mMotionPopup.show(mDesktopView);
        } else if (id == R.id.remote_mode) {
            if (null == mDesktopModePopup) {
                mDesktopModePopup = new DesktopModePopup(mActivity);
                mDesktopModePopup.setOnSubViewClickListener(mEventListener);
            }
            mDesktopModePopup.setCurrentMode(getCurrentDesktopMode());
            mDesktopModePopup.show(mDesktopView);
        }
        mOpPopup.dismiss();
    }

    /**
     * 模式切换
     *
     * @param v 目标view
     */
    private void handleDesktopMode(View v) {
        int id = v.getId();
        if (id == R.id.hd_mode) {
            if (null != mDesktopManager) {
                if (!mDesktopManager.isSupportNewHDMode()) {                  // 被控端不支持
                    ToastUtils.showSingleToast("当前被控版本不支持高清模式，建议升级被控端以获得更好体验", getBaseContext());
                } else {
                    changeMode(MODE_HD);
                }
            }
        } else if (id == R.id.smooth_mode) {
            changeMode(MODE_SMOOTH);
        } else if (id == R.id.speed_mode) {
            changeMode(MODE_SPEED);
        }
        mDesktopModePopup.dismiss();
    }

    /**
     * 切换桌面模式以及修改帧率
     *
     * @param mode 高清 游戏 急速
     */
    private void changeMode(int mode) {
        this.changeMode = mode;
        isLoadingChangeModel = true;
        //  修改最大帧率
        //  CompressionBuild.buildMaxFPS(mDesktopManager,30);
        // 切换模式 默认帧率30帧
        CompressionBuild.setCompressMode(mode, mDesktopManager);
        //   CompressionBuild.setCompressMode(mode, mDesktopManager ,30);
        if (null != remoteDesktopUtils) remoteDesktopUtils.changeDesktopMode(this);
    }

    /**
     * 切换屏幕
     */
    private void switchScreen() {
        int index = mDesktopManager.getScreenIndex();
        int count = mDesktopManager.getScreenCount();
        if (index == count - 1) {
            index = 0;
        } else {
            index++;
        }
        mDesktopManager.switchScreen(index);
        Toast.makeText(mActivity, "屏幕切换", Toast.LENGTH_SHORT).show();
    }

    /**
     * 开启关闭声音
     */
    public void switchVoice() {
        boolean isChecked = mCb_desktop_menu_voice_checkbox.isChecked();
        if (isChecked) {
            soundStopCapture();
            Toast.makeText(mActivity, "关闭声音", Toast.LENGTH_SHORT).show();
            mTv_desktop_menu_voice.setText("开启声音");
            mCb_desktop_menu_voice_checkbox.setChecked(false);
        } else {
            soundStartCapture();
            Toast.makeText(mActivity, "开启声音", Toast.LENGTH_SHORT).show();
            mTv_desktop_menu_voice.setText("关闭声音");
            mCb_desktop_menu_voice_checkbox.setChecked(true);
        }
    }


    /**
     * 隐藏相应功能 在显示 Operation 操作工具栏之前
     *
     * @param view       目标view
     * @param functionId 功能id
     */
    private void hideOperationFunction(View view, int functionId) {
        switch (functionId) {
            case FUNCTION_LOCK_SCREEN:
                hideSubView(view, R.id.remote_option_lockscreen);
                break;
            case FUNCTION_CLOSE_MOUSE:
                hideSubView(view, R.id.remote_option_close_mouse);
                break;
            case FUNCTION_SHOW_DESKTOP:
                hideSubView(view, R.id.show_remote_desktop);
                break;
            case FUNCTION_LOCK_DESKTOP:
                hideSubView(view, R.id.lock_remote_desktop);
                break;
            case FUNCTION_RESTART:
                hideSubView(view, R.id.restart_remote_host);
                break;
            case FUNCTION_CLOSE_REMOTE_DESKTOP:
                hideSubView(view, R.id.close_remote_host);
                break;
            case FUNCTION_GUIDE:
                hideSubView(view, R.id.operation_gesture_guide);
                break;
        }
    }

    public static void showSubView(View rootView, int res) {
        View view = rootView.findViewById(res);
        if (null != view) view.setVisibility(View.VISIBLE);
    }

    public static void hideSubView(View rootView, int res) {
        View view = rootView.findViewById(res);
        if (null != view) view.setVisibility(View.GONE);
    }

    /**
     * 鼠标菜单
     */
    private void showMouseMenuPopupWindow() {
        if (null == mMouseMenuPop) mMouseMenuPop = new MouseMenuPopup(this, mDesktopManager);
        mMouseMenuPop.setOnDismissListener(() -> {
            if (!mouse.isShown()) mouse.setVisibility(View.VISIBLE);
        });
        mMouseMenuPop.show(mDesktopView);
    }

    private void handleMotion(View v) {
        if (v.getId() == R.id.btnClose) {
            mMotionPopup.dismiss();
        }
    }

    /**
     * 开启/关闭远程桌面可控制模式
     *
     * @param control true 开启.
     */
    private void enableControl(boolean control) {
        if (control) {
            mMode = MODE_CONTROL;
        } else {
            mMode = MODE_OBSERVE;
        }
    }

    /**
     * 远程桌面可控制模式
     *
     * @return true 处于控制模式.
     */
    public boolean isControl() {
        return MODE_CONTROL == mMode;
    }

    @Override
    public void onBackPressed() {
        if (null != mMouseMenuPop && mMouseMenuPop.isShowing()) {
            mMouseMenuPop.dismiss();
        } else if (null != mMotionPopup && mMotionPopup.isShowing()) {
            mMotionPopup.dismiss();
        } else if (null != mOpPopup && mOpPopup.isShowing()) {
            mOpPopup.dismiss();
            mMenuToolBar.setVisibility(View.INVISIBLE);
            mMenuPopBar.setVisibility(View.VISIBLE);
        } else if (null != mKeyboardCtrlView && mKeyboardCtrlView.isShow()) {
            clearKeyboardCtrlDown();
            mKeyboardCtrlView.performSubViewClick(R.id.btn_id_pack_up);
        } else {
            stopRemoteConnected();
        }
    }

    /**
     * 控制键盘按键处理
     *
     * @param v 目标view
     */
    private void handleKeyboardCtrl(View v) {
        int vId = v.getId();
        if (R.id.btn_id_pack_up == vId) {
            clearKeyboardCtrlDown();
            mKeyboardCtrlView.hide();
            KeyBoardUtils.hideSoftInput(mDesktopView);
            hideKeyboardCtrlView();
            hideKeyboardBaseView();
            hideKeyboardFunView();
            mMenuToolBar.setVisibility(View.GONE);
            mMenuPopBar.setVisibility(View.VISIBLE);
        } else if (R.id.btn_id_more_one == vId) {
            // 更多
            switchKeyboardFunBaseSoft(false);
        } else {
            switchKeyboardFunBaseSoft(true);
            String mKeycode_Up = KeyboardCtrlView.mKey.get(v.getId());
            boolean isPressed = v.isPressed();
            sendKeyUpDown(mKeycode_Up, 0, isPressed);
        }
    }

    /**
     * 按业务要求切换输入键盘
     *
     * @param func true功能键; false 更多
     */
    private void switchKeyboardFunBaseSoft(boolean func) {
        boolean funDown = mKeyboardCtrlView.isFunDown();
        boolean moreDown = mKeyboardCtrlView.isMoreDown();
        if (!funDown && !moreDown) {
            KeyBoardUtils.showSoftInput(mDesktopView);
            hideKeyboardBaseView();
            hideKeyboardFunView();
        } else if ((funDown && moreDown && func) || (funDown && !moreDown)) {
            KeyBoardUtils.hideSoftInput(mDesktopView);
            showKeyboardBaseView();
            hideKeyboardFunView();
        } else {
            KeyBoardUtils.hideSoftInput(mDesktopView);
            hideKeyboardBaseView();
            showKeyboardFunView();
        }
    }

    /**
     * 基础键盘按键处理
     *
     * @param v 目标view
     */
    private void handleKeyboardBase(View v) {
        String keyCode = KeyboardBaseView.mKey.get(v.getId());
        sendKeyUpDown(keyCode, 0, true);
        sendKeyUpDown(keyCode, 0, false);
        clearKeyboardCtrlDown();
        switchKeyboardFunBaseSoft(true);

    }

    /**
     * 功能键盘按键处理
     *
     * @param v     目标view
     * @param event 事件
     * @return 返回状态
     */
    private boolean handleKeyboardFunKey(View v, MotionEvent event) {
        int action = event.getAction();
        String keyCode = KeyboardFunView.mKey.get(v.getId());
        if (action == MotionEvent.ACTION_DOWN) {
            sendKeyUpDown(keyCode, 0, true);
        } else if (action == MotionEvent.ACTION_UP
                || action == MotionEvent.ACTION_OUTSIDE
                || action == MotionEvent.ACTION_CANCEL) {
            sendKeyUpDown(keyCode, 0, false);
        }
        return false;
    }

    /**
     * 显示控制键盘
     */
    private void showKeyboardCtrlView() {
        if (null == mKeyboardCtrlView) {
            ViewStub vs = rootView.findViewById(R.id.desktop_keyboard_ctrl_viewstub);
            View v = vs.inflate();
            mKeyboardCtrlView = new KeyboardCtrlView(v);
            mKeyboardCtrlView.setOnSubViewClickListener(mEventListener);
        }
        mKeyboardCtrlView.show();
        mDesktopView.setKeyboardHeight(DisplayUtils.dp2px(50, mActivity));
    }

    /**
     * 显示基础键盘
     */
    private void showKeyboardBaseView() {
        if (null == mKeyboardBaseView) {
            ViewStub vs = rootView.findViewById(R.id.desktop_keyboard_base_viewstub);
            View v = vs.inflate();
            mKeyboardBaseView = new KeyboardBaseView(v);
            mKeyboardBaseView.setOnSubViewClickListener(mEventListener);
        }
        mKeyboardBaseView.show();
        mDesktopView.setKeyboardViewHeight(DisplayUtils.dp2px(140, mActivity));
    }

    /**
     * 显示功能键盘
     */
    private void showKeyboardFunView() {
        if (null == mKeyboardFunView) {
            ViewStub vs = rootView.findViewById(R.id.desktop_keyboard_fun_viewstub);
            View v = vs.inflate();
            mKeyboardFunView = new KeyboardFunView(v);
            mKeyboardFunView.setOnSubViewTouchListener(mEventListener);
        }
        mKeyboardFunView.show();
        mDesktopView.setKeyboardViewHeight(DisplayUtils.dp2px(140, mActivity));
    }

    /**
     * 隐藏控制键盘
     */
    private void hideKeyboardCtrlView() {
        if (null != mKeyboardCtrlView) {
            mKeyboardCtrlView.hide();
            mDesktopView.adjustView();
            mDesktopView.setKeyboardHeight(0);
        }
    }

    /**
     * 隐藏基础键盘
     */
    private void hideKeyboardBaseView() {
        if (null != mKeyboardBaseView) {
            mKeyboardBaseView.hide();
            mDesktopView.adjustView();
            mDesktopView.setKeyboardViewHeight(0);
        }
    }

    /**
     * 隐藏功能键盘
     */
    private void hideKeyboardFunView() {
        if (null != mKeyboardFunView) {
            mKeyboardFunView.hide();
            mDesktopView.adjustView();
            mDesktopView.setKeyboardViewHeight(0);
        }
    }

    /**
     * 按键处理
     *
     * @param key
     * @param metaState
     * @param isDown
     */
    private void sendKeyUpDown(String key, int metaState, boolean isDown) {
        mDesktopManager.sendKeyUpDown(key, metaState, isDown);
    }

    /**
     * 清除按键状态
     */
    private void clearKeyboardCtrlDown() {
        if (mKeyboardCtrlView.isCtrlDown()) mKeyboardCtrlView.performSubViewClick(R.id.btn_id_ctrl);
        if (mKeyboardCtrlView.isShiftDown())
            mKeyboardCtrlView.performSubViewClick(R.id.btn_id_shift);
        if (mKeyboardCtrlView.isAltDown()) mKeyboardCtrlView.performSubViewClick(R.id.btn_id_alt);
        if (mKeyboardCtrlView.isWinDown()) mKeyboardCtrlView.performSubViewClick(R.id.btn_id_win);
        if (mKeyboardCtrlView.isMoreDown())
            mKeyboardCtrlView.performSubViewClick(R.id.btn_id_more_one);
    }

    @Override
    public void onPause() {
        super.onPause();
        mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        mActivity.setRequestedOrientation(mScreenOrientation);

        if (mDesktopManager != null) mDesktopManager.receiveImageData(false);
    }

    @Override
    public void onResume() {
        super.onResume();
        mScreenOrientation = mActivity.getRequestedOrientation();
        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
        mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        mDesktopView.requestFocus();
        if (BuildConfig.hasQ() && !isFirstInit && null != mHandler) {
            mHandler.postDelayed(() -> ClipboardUtils.asyncClipboard(mDesktopManager, this), 1000);
        }
        if (isFirstInit) isFirstInit = false;

        screenHeight = 0;
        if (null != mDesktopManager) mDesktopManager.receiveImageData(true);
    }

    @Override
    public void onStatusChanged(int nStatus, int nError) {
        if (CNTS.DISCONNECTED == nStatus) {
            // 断开连接后销毁所有GrepView弹出的pop
            Toast.makeText(mActivity, "远程连接已断开", Toast.LENGTH_SHORT).show();
            stopRemoteConnected();
        }

    }

    /**
     * 屏幕纵横屏发生改变时
     */
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        screenHeight = 0;
        if (null != mouse) {
            if (mouse.isSmall()) {
                // 增加右侧菜单栏边距，不与菜单栏重叠
                mouse.setTranslationX(DisplayUtils.getScreenWidth(this) - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2 +
                        Mouse.SMALL_MOUSE_SIZE / 2 + Mouse.REMOTE_FUNCTION_MENU_WIDTH, this));
                mouse.setTranslationY(DisplayUtils.dp2px(50, this));
            } else {
                mouse.setTranslationX((DisplayUtils.getScreenWidth(this) >> 1) - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, this));
                mouse.setTranslationY((DisplayUtils.getScreenHeight(this) >> 1) - DisplayUtils.dp2px(Mouse.VIEW_SIZE / 2, this));
            }
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction() & MotionEvent.ACTION_MASK;
        if (null != mKeyboardCtrlView && !mKeyboardCtrlView.isShow()
                && action == MotionEvent.ACTION_DOWN || mMenuToolBar.isShown()
                && action == MotionEvent.ACTION_DOWN) {
            // 点击区域远程桌面上处理
            mMenuToolBar.getHitRect(temp);
            if (!temp.contains((int) ev.getX(), (int) ev.getY())) {
                mMenuToolBar.setVisibility(View.INVISIBLE);
                mMenuPopBar.setVisibility(View.VISIBLE);
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 连接声音插件
     */
    private void ConnectSoundPlugin() {
        if (address != null && session != null && !"".equals(address) && !"".equals(session)) {
            mSndListener = new SoundListener();
            mSoundManager.addPluginListener(mSndListener);
            PluginParam param = new PluginParam();
            param.setAddress(address);
            param.setSession(session);
            param.setAllowKcp(false);
            bConnect = mSoundManager.connectPlugin(param);
            Log.i(TAG, "bConnect: " + bConnect + "address : " + address + "session : " + session);
        }
    }

    /**
     * 开启声音
     */
    public void soundStartCapture() {
        mSoundManager.startCapture();
    }

    /**
     * 关闭声音
     */
    public void soundStopCapture() {
        mSoundManager.stopCapture();
    }

    class SoundListener implements IRemoteSoundChatListener {

        @Override
        public void onStatusChanged(int nStatus, int nError) {
        }
    }

    private boolean isStopConnected = false;

    /**
     * 停止远控连接
     */
    private void stopRemoteConnected() {
        isStopConnected = true;
        new StopPluginTask().execute();
    }

    @SuppressLint("StaticFieldLeak")
    private class StopPluginTask extends AsyncTask<Void, Void, Boolean> {
        @Override
        protected void onPreExecute() {
            if (null != mLoadingDialog && !isDestroyed() && !isFinishing()) mLoadingDialog.show();
        }

        @Override
        protected Boolean doInBackground(Void... voids) {
            cancelSndJni();
            disconnectedDesktopPlugin();
            return true;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            if (null != mLoadingDialog && !isDestroyed() && !isFinishing()) mLoadingDialog.dismiss();
            if(!isDestroyed() && !isFinishing()){
                finish();
            }
        }
    }

    /**
     * 断开声音插件
     */
    public void cancelSndJni() {
        if (bConnect) {
            mSoundManager.removePluginListener(mSndListener);
            mSoundManager.removeConnectorListener(this);
            mSoundManager.stopCapture();
            mSoundManager.cancelPlugin();
        }
    }

    /**
     * 断开远程桌面插件
     */
    private void disconnectedDesktopPlugin() {
        if (null != mDesktopManager) {
            mDesktopManager.removeListener(this);
            mDesktopManager.removeConnectorListener(this);
            mDesktopManager.cancelPlugin();
        }
    }

    @Override
    public void onTimeOut() {
        finish();
    }

    @Override
    public void onDestroy() {
        isCancelDesktop = true;
        if (null != codecUtils) codecUtils.releaseMediaCodec();
        if (null != mOpPopup) mOpPopup.dismiss();
        if (null != mMotionPopup) mMotionPopup.dismiss();
        if (null != mMouseMenuPop) mMouseMenuPop.dismiss();
        if (null != mSurfaceView) mSurfaceView.destroySurfaceView();
        if (null != remoteDesktopUtils) remoteDesktopUtils.closeChangeModeDialog();
        if (null != mDesktopManager) mDesktopManager.shutDownSurface();
        ClipboardUtils.stopClipMonitorService(this);
        DisplayUtils.quitFullScreenStatus(this);
        if(!isStopConnected){
            stopRemoteConnected();
        }
        super.onDestroy();
    }
}
